package com.ruoyi.game.core;

import com.ruoyi.game.constant.GameRoomProperties;
import com.ruoyi.game.core.card.BasePoker;
import com.ruoyi.game.core.card.CardPower;
import com.ruoyi.game.core.card.CardTypeChecker;
import com.ruoyi.game.constant.GameErrorCode;
import com.ruoyi.game.websocket.handler.GameWebSocketHandler;
import com.ruoyi.game.websocket.message.packet.RoundEndPush;
import com.ruoyi.game.websocket.message.packet.WsPacket;
import com.ruoyi.game.websocket.message.packet.WsPackets;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Data
@RequiredArgsConstructor
public class GameRoundCore {
    private final GameWebSocketHandler socketHandler;      // WebSocket 通信句柄
    private final GameRoomProperties gameRoomProperties;
    private final GameSetCore roomSet;
    private final int roundId;
    private final Map<Integer, GameRoundPos> roundPosMap = new HashMap<>();     //每个位置的玩家
    private final long startTime;
    private final List<Integer> roundCards = new ArrayList<>();         // 当前回合已打出的所有牌
    private List<Integer> firstOutCards = new ArrayList<>();            // 第一次出牌的牌型
    private int firstOutSeat = -1;                                      // 收出牌位置

    private int winnerSeat = -1;
    private int currentTurnSeat = -1;      // 当前轮到谁出牌
    private final CardTypeChecker cardTypeChecker = new CardTypeChecker();

    public GameRoundCore(GameSetCore roomSet, int roundId) {
        this.roomSet = roomSet;
        this.roundId = roundId;
        this.startTime = System.currentTimeMillis() / 1000;
        this.socketHandler = roomSet.getSocketHandler();
        this.gameRoomProperties = roomSet.getGameRoomProperties();
        log.info("[GameRoundCore] 启动回合 roundId={} 当前Set={}", roundId, roomSet.getSetId());
    }

    // 添加一个等待操作的玩家
    public void addWaitingPlayer(int seatIndex, PKOpType opType) {
        GameRoundPos roundPos = new GameRoundPos(seatIndex);
        roundPos.getReceiveOpTypes().add(opType);
        roundPosMap.put(seatIndex, roundPos);
        log.info("[GameRoundCore:{}] 玩家 seat={} 被添加到等待操作列表，操作类型={}", roundId, seatIndex, opType);
    }

    /**
     * 回合更新逻辑：
     * - 检查每个 seat 是否操作超时（用于踢人处理）
     * - 不负责调用 endRound()，不负责推进阶段
     * - 返回值仅表示当前回合是否所有人已完成操作（供外部决定是否推进）
     */
    public boolean update(int sec) {
        boolean allOpDone = true;
        for (GameRoundPos roundPos : roundPosMap.values()) {
            if (!roundPos.isOperated()) {
                allOpDone = false;
                long now = System.currentTimeMillis() / 1000;
                long start = roundPos.getOpStartTime();
                if (start > 0 && now - start > gameRoomProperties.getCardoutTimeLimit()) {
                    GameRoomPos gameRoomPos = roomSet.getRoom().getSeats().get(roundPos.getSeatIndex());
                    if (gameRoomPos != null) {
                        roomSet.getRoom().endSet();
                        roomSet.getRoom().kickOutPlayer(roundPos.getSeatIndex(), "操作超时，自动踢出", "超时未操作");
                        log.info("[GameRoundCore:{}] 玩家 seat={} 操作超时，自动踢出，结束牌局", roundId, roundPos.getSeatIndex());
                    }
                }
            }
        }

        return allOpDone;
    }

    public boolean allPlayerOperated() {
        return roundPosMap.values().stream().allMatch(roundPos ->
                roundPos.getReceiveOpTypes().isEmpty() || roundPos.isOperated()
        );
    }

    public boolean recordOp(int seatIndex) {
        GameRoundPos roundPos = roundPosMap.get(seatIndex);
        if (roomSet.getState() != SetState.CALL_ZHU_STATE) {
            if (roundPos == null || roundPos.isOperated()) {
                GameRoomPos gameRoomPos = roomSet.getRoom().getSeats().get(seatIndex);
                WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(gameRoomPos.getPlayerId());
                if (gameRoomPos != null && session != null) {
                    socketHandler.sendError(session, GameErrorCode.INVALID_OP, "非法操作或重复出牌");
                }
                log.warn("[GameRoundCore:{}] seat={} 无权记录出牌", roundId, seatIndex);
                return false;
            }
        }

        roundPos.markOperated(); // ✅ 只做标记
        // 可以记录出牌列表，首出位置，或者用于 UI 展示
        return true;
    }

    private CardPower getWinnerPower() {
        return roundPosMap.get(winnerSeat).getCardPower();
    }

    public void recordPlayerCards(int seatIndex, List<Integer> cards) {
        GameRoundPos roundPos = roundPosMap.get(seatIndex);
        if (roundPos == null) {
            GameRoomPos gameRoomPos = roomSet.getRoom().getSeats().get(seatIndex);
            WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(gameRoomPos.getPlayerId());
            if (gameRoomPos != null && session != null) {
                socketHandler.sendError(session, GameErrorCode.PLAYER_NOT_FOUND, "座位不存在或未找到");
            }
            log.warn("[GameRoundCore:{}] 无效的出牌 seat={}", roundId, seatIndex);
            return;
        }

        roundPos.setCards(cards); // 保存出牌

        // 评估牌型大小
        CardPower power = cardTypeChecker.evaluatePower(cards, this);
        roundPos.setCardPower(power);

        if (winnerSeat == -1 || power.compareTo(getWinnerPower()) > 0) {
            winnerSeat = seatIndex;
            roomSet.setLatestWinnerSeat(seatIndex);
            log.info("[WINNER - GameRoundCore:{}] 玩家 {} 出牌：{}，评分结构={}", roundId, seatIndex, BasePoker.toCardString(cards), power);
        }
    }

    public Map<Integer, List<Integer>> getRemainingCards() {
        Map<Integer, List<Integer>> remainCards = new HashMap<>();
        for (Map.Entry<Integer, GameSetPos> entry : roomSet.getPlayerMap().entrySet()) {
            remainCards.put(entry.getKey(), new ArrayList<>(entry.getValue().getHandCards()));
        }
        return remainCards;
    }

    public void endRound() {
        int roundScore = roomSet.addRoundScore(winnerSeat);

        // ✅ 推送回合得分广播
        int totalScore = roomSet.getCurK510Point();
        int winnerTeamId = roomSet.getTeamId(winnerSeat);

        List<Integer> winnerCards = roundPosMap.get(winnerSeat) != null
                ? roundPosMap.get(winnerSeat).getCards()
                : Collections.emptyList();


        log.info("[GameRoundCore:{}] 回合结束", roundId);
        log.info("[GameRoundCore:{}] 胜者 seat={}，出牌={}",
                roundId, winnerSeat, BasePoker.toCardString(winnerCards));
        log.info("[GameRoundCore:{}] 首出牌 seat={}，出牌={}",
                roundId,
                firstOutSeat,
                BasePoker.toCardString(firstOutCards));
        log.info("[GameRoundCore:{}] 回合全部出牌={}", roundId, BasePoker.toCardString(roundCards));

        // 保存当前 roundCards 到 GameSetCore 中 lastRoundCards
        roomSet.setPrevRoundCards(new ArrayList<>(roundCards));

        // 构建每个玩家的剩余手牌
        Map<Integer, List<Integer>> remainCards = getRemainingCards();

        WsPacket<RoundEndPush> packet = WsPackets.roundEnd(
                winnerSeat,
                winnerTeamId,
                roundScore,
                totalScore,
                remainCards,
                new ArrayList<>(roundCards),
                roomSet.getPrevRoundCards()
        );
        socketHandler.broadcastPacketToRoom(roomSet.getRoom().getRoomId(), packet);
        roomSet.notifyScoreMultiplierIfChanged();

        // 清空回合记录
        this.getRoundCards().clear();
        this.getFirstOutCards().clear();
    }

    public boolean isFirstOut() {
        return roundCards.isEmpty();
    }

    /**
     * 查找下一位未出牌的 seatIndex（从当前 seatIndex 开始顺时针寻找）
     */
    public Integer findNextSeat(int currentSeat) {
        List<Integer> seatList = new ArrayList<>(roundPosMap.keySet());
        seatList.sort(Integer::compareTo); // 确保顺序一致性

        int index = seatList.indexOf(currentSeat);
        int total = seatList.size();

        for (int i = 1; i < total; i++) {
            int nextIndex = (index + i) % total;
            int nextSeat = seatList.get(nextIndex);
            GameRoundPos nextPos = roundPosMap.get(nextSeat);
            if (nextPos != null && !nextPos.isOperated()) {
                return nextSeat;
            }
        }

        return -1;
    }

    /**
     * 查找当前座位的上一家 seatIndex（从当前 seatIndex 逆时针寻找）
     */
    public Integer findPrevSeat(int currentSeat) {
        List<Integer> seatList = new ArrayList<>(roundPosMap.keySet());
        seatList.sort(Integer::compareTo); // 确保顺序一致

        int index = seatList.indexOf(currentSeat);
        int total = seatList.size();

        for (int i = 1; i < total; i++) {
            int prevIndex = (index - i + total) % total;
            int prevSeat = seatList.get(prevIndex);
            GameRoundPos prevPos = roundPosMap.get(prevSeat);
            if (prevPos != null && prevPos.isOperated()) {
                return prevSeat;
            }
        }

        return null; // 没找到上一家已出牌的玩家
    }

    /**
     * 是否首出（即当前回合还未有玩家出牌）
     */
    public boolean isFirstOp() {
        return firstOutCards == null || firstOutCards.isEmpty();
    }

    public Map<Integer, List<Integer>> buildRoundCardMap() {
        return roundPosMap.values().stream()
                .filter(pos -> pos.getCards() != null && !pos.getCards().isEmpty())
                .collect(Collectors.toMap(GameRoundPos::getSeatIndex, GameRoundPos::getCards));
    }
}
